package jinyilw.swing;

import jinyilw.common.Operator;

import java.awt.AlphaComposite;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class ComponentTools
{
	public static final AlphaComposite alphaComposite = AlphaComposite
			.getInstance(AlphaComposite.SRC_OVER, 1);
	public static Cursor handCursor = Cursor
			.getPredefinedCursor(Cursor.HAND_CURSOR);
	public static final int[] cursorMapping = new int[]{Cursor.NW_RESIZE_CURSOR,
			Cursor.NW_RESIZE_CURSOR, Cursor.N_RESIZE_CURSOR,
			Cursor.NE_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR,
			Cursor.NW_RESIZE_CURSOR, 0, 0, 0, Cursor.NE_RESIZE_CURSOR,
			Cursor.W_RESIZE_CURSOR, 0, 0, 0, Cursor.E_RESIZE_CURSOR,
			Cursor.SW_RESIZE_CURSOR, 0, 0, 0, Cursor.SE_RESIZE_CURSOR,
			Cursor.SW_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR,
			Cursor.S_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR,
			Cursor.SE_RESIZE_CURSOR};

	private ComponentTools()
	{
	}

	public static Composite applyAlpha(Graphics2D g2d, float alpha)
	{
		if (alpha >= 1f)
			return null;
		Composite composite = g2d.getComposite();
		g2d.setComposite(alphaComposite.derive(alpha));
		return composite;
	}

	public static Composite applyEnableAlpha(Graphics2D g2d, boolean isEnable,
			float a, float da)
	{
		return applyAlpha(g2d, isEnable ? a : da);
	}

	public static Composite applyEnableAlpha(Graphics2D g2d, Component c,
			float a, float da)
	{
		return applyAlpha(g2d, c.isEnabled() ? a : da);
	}

	public static void clickToClose(final Component clickComponent,
			final Window closeWindow)
	{
		clickComponent.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mouseClicked(MouseEvent e)
			{
				closeWindow.dispose();
			}
		});
	}

	public static void clickToHide(final Component clickComponent,
			final Frame hideFrame)
	{
		clickComponent.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mouseClicked(MouseEvent e)
			{
				hideFrame.setExtendedState(Frame.ICONIFIED);
			}
		});
	}

	public static void addClickOperator(final Component component,
			final Operator<?> operator)
	{
		component.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mouseClicked(MouseEvent e)
			{
				operator.operate(null);
			}
		});
	}


	public static void moveComponentInThread(final Component component,
			final int x, final int y)
	{
		moveComponentInThread(component, x, y, 80);
	}

	public static void moveComponentInThread(final Component component,
			final int x, final int y, final int step)
	{
		new Thread(() -> moveComponent(component, x, y, step)).start();

	}

	public static void moveComponent(Component component, int x, int y,
			int step)
	{
		if (step <= 0)
			return;
		final Point location = component.getLocation();
		int xx = 1, yy = 1;
		if (x < location.x)
			xx = -1;
		if (y < location.y)
			yy = -1;
		final int xVar = (x - location.x) / step + xx;
		final int yVar = (y - location.y) / step + yy;

		boolean absX, absY;
		do
		{
			absX = Math.abs(x - location.x) > Math.abs(xVar);
			absY = Math.abs(y - location.y) > Math.abs(yVar);
			if (absX)
				location.x += xVar;
			if (absY)
				location.y += yVar;
			component.setLocation(location);
			component.repaint();
			try
			{
				Thread.sleep(5);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		} while (absX || absY);

		component.setLocation(x, y);
		component.repaint();
	}

	public static boolean isLeftToRight(Component c)
	{
		if (c == null)
		{
			return true;
		}
		return c.getComponentOrientation().isLeftToRight();
	}

	public static FontMetrics getFontMetrics(Component c, Graphics g, Font f)
	{
		FontMetrics fm = null;
		if (g == null && c != null)
		{
			g = c.getGraphics();
		}
		if (g != null)
		{
			fm = (f != null) ? g.getFontMetrics(f) : g.getFontMetrics();
		} else if (c != null)
		{
			fm = (f != null)
					? c.getFontMetrics(f)
					: c.getFontMetrics(c.getFont());
		}
		return fm;
	}

	public static void toFront(Component c)
	{
		if (c == null)
			return;
		Container parent = c.getParent();
		if (parent != null)
			parent.setComponentZOrder(c, 0);
	}
}
